﻿using FastMvc.Auth;
using FastMvc.Crud;
using FastMvc.Crud.Models;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace FastMvc.Repositories
{
    /// <summary>
    /// 仓库类
    /// </summary>
    public interface IRepository<TEntity, TPrimaryKey>
        where TEntity : DBEntity<TPrimaryKey>, new()
    {
        UserAuthInfo UserAuth { get; set; }
        SqlSugarRepository<TEntity, TPrimaryKey> IgnorGlobalFilters();

        #region Query
        IEnumerable<TEntity> GetAll();

        Task<IEnumerable<TEntity>> GetAllAsync();

        TEntity Get(TPrimaryKey sId);

        Task<TEntity> GetAsync(TPrimaryKey sId);

        IEnumerable<TEntity> GetAll(Expression<Func<TEntity, bool>> expression);

        Task<IEnumerable<TEntity>> GetAllAsync(Expression<Func<TEntity, bool>> expression);

        TEntity Single(Expression<Func<TEntity, bool>> expression);

        Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> expression);

        TEntity FirstOrDefault(Expression<Func<TEntity, bool>> expression);

        Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> expression);

        #endregion

        #region Insert
        TEntity Insert(TEntity entity);

        Task<TEntity> InsertAsync(TEntity entity);

        TPrimaryKey InsertReturnId(TEntity entity);

        Task<TPrimaryKey> InsertRetrunIdAsync(TEntity entity);

        #endregion

        #region Update
        void Update(TEntity entity);

        Task UpdateAsync(TEntity entity);
        #endregion

        #region Delete
        void Delete(TEntity entity);

        Task DeleteAsync(TEntity entity);

        void Delete(TPrimaryKey id);

        Task DeleteAsync(TPrimaryKey id);

        void Delete(Expression<Func<TEntity, bool>> expression);

        Task DeleteAsync(Expression<Func<TEntity, bool>> expression);
        #endregion

        #region Aggregates
        int Count();

        Task<int> CountAsync();

        int Count(Expression<Func<TEntity, bool>> expression);

        Task<int> CountAsync(Expression<Func<TEntity, bool>> expression);

        bool Any();

        Task<bool> AnyAsync();

        bool Any(Expression<Func<TEntity, bool>> expression);

        Task<bool> AnyAsync(Expression<Func<TEntity, bool>> expression);

        #endregion

        #region Trans
        void RunTrans(Action<IRepository<TEntity, TPrimaryKey>> iAct);

        Task RunTransAsync(Action<IRepository<TEntity, TPrimaryKey>> iAct);
        #endregion
    }

    public interface IRepository<TEntity> : IRepository<TEntity, string>
        where TEntity : DBEntity<string>, new()
    { }

    public interface IRepository<TEntity, TPrimaryKey, T2> : IRepository<TEntity, TPrimaryKey>
        where TEntity: DBEntity<TPrimaryKey>, new()
    {
        IEnumerable<KeyValuePair<TEntity,T2>> JoinQuery(DBJoinType joinType, Expression<Func<TEntity,T2,bool>> joinExpress, Expression<Func<TEntity, T2, bool>> whereExpress);
    }

    public enum DBJoinType
    {
        Left,
        Right,
        Inner
    }
}
